In [1]:
import cv2
import numpy as np
from tqdm import tqdm
import pandas as pd
import os, time
import random
import matplotlib.pyplot as plt
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
In [2]:
from keras.utils.np_utils import to_categorical # convert to one-hot-encoding
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Dropout, Flatten, Conv2D, MaxPool2D, GlobalAveragePooling2D, BatchNormalization
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import LearningRateScheduler, TensorBoard
from keras.applications.inception_v3 import InceptionV3, preprocess_input
In [3]:
project_name = 'Dog_Breed_Identification'
step_name = 'InceptionV3FineTune'
date_str = time.strftime("%Y%m%d", time.localtime())
time_str = time.strftime("%Y%m%d_%H%M%S", time.localtime())
run_name = project_name + '_' + step_name + '_' + time_str
print('run_name: ' + run_name)
In [4]:
cwd = os.getcwd()
input_path = os.path.join(cwd, 'input')
log_path = os.path.join(cwd, 'log')
model_path = os.path.join(cwd, 'model')
output_path = os.path.join(cwd, 'output')
print('input_path: ' + input_path)
print('log_path: ' + log_path)
print('model_path: ' + model_path)
print('output_path: ' + output_path)
In [5]:
cwd = os.getcwd()
df = pd.read_csv(os.path.join(cwd, 'input', 'labels.csv'))
print('lables amount: %d' %len(df))
df.head()
Out[5]:
In [6]:
n = len(df)
breed = set(df['breed'])
n_class = len(breed)
breed = sorted(breed)
print(breed)
class_to_num = dict(zip(breed, range(n_class)))
num_to_class = dict(zip(range(n_class), breed))
In [7]:
def build_model():
# create the base pre-trained model
base_model = InceptionV3(weights='imagenet', include_top=False)
# add a global spatial average pooling layer
x = base_model.output
x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(2048, activation='relu')(x)
x = Dense(2048, activation='relu')(x)
# and a logistic layer -- let's say we have 200 classes
predictions = Dense(120, activation='softmax')(x)
# this is the model we will train
model = Model(inputs=base_model.input, outputs=predictions)
# first: train only the top layers (which were randomly initialized)
# i.e. freeze all convolutional InceptionV3 layers
for layer in base_model.layers:
layer.trainable = False
model.compile(optimizer = Adam(lr=1e-4), loss = 'categorical_crossentropy', metrics = ['accuracy'])
return model
In [8]:
model = build_model()
# model.summary()
In [9]:
def saveModel(model, run_name):
cwd = os.getcwd()
modelPath = os.path.join(cwd, 'model')
if not os.path.isdir(modelPath):
os.mkdir(modelPath)
weigthsFile = os.path.join(modelPath, run_name + '.h5')
model.save(weigthsFile)
# saveModel(model, 'saveModel_test')
In [10]:
data_train_path = os.path.join(input_path, 'data_train')
data_val_path = os.path.join(input_path, 'data_val')
data_test_path = os.path.join(input_path, 'data_test')
image_size = (299, 299)
seed = 3
batch_size = 64
# gen = ImageDataGenerator()
train_gen = ImageDataGenerator(rescale=1./255,
rotation_range = 20,
zoom_range = 0.1,
width_shift_range = 0.1,
height_shift_range = 0.1,
horizontal_flip = True,
vertical_flip = True)
val_gen = ImageDataGenerator(rescale=1./255,
rotation_range = 20,
zoom_range = 0.1,
width_shift_range = 0.1,
height_shift_range = 0.1,
horizontal_flip = True,
vertical_flip = True)
test_gen = ImageDataGenerator(rescale=1./255)
train_generator = train_gen.flow_from_directory(data_train_path,
target_size=image_size,
shuffle=True,
seed=seed,
class_mode = "categorical",
batch_size=batch_size)
val_generator = val_gen.flow_from_directory(data_val_path,
target_size=image_size,
shuffle=False,
# seed=seed,
class_mode = "categorical",
batch_size=batch_size)
test_generator = test_gen.flow_from_directory(data_test_path,
target_size=image_size,
shuffle=False,
class_mode = "categorical",
batch_size=batch_size)
print(train_generator.classes[0:100])
print(val_generator.classes[0:100])
print(test_generator.classes[0:100])
In [11]:
# def get_lr(x):
# lr = round(1e-3 * 0.9 ** x, 6)
# if lr < 1e-4:
# lr = 1e-4
# print(lr, end=' ')
# return lr
def get_lr(x):
n = 20
lr = 1e-3
if x > n:
lr = round(1e-3 * 0.9 ** (x-n), 6)
if lr < 1e-4:
lr = 1e-4
print(lr, end=' ')
return lr
get_lr(10) # Test
get_lr(15) # Test
get_lr(20) # Test
get_lr(30) # Test
get_lr(40) # Test
get_lr(50) # Test
# annealer = LearningRateScheduler(lambda x: 1e-3 * 0.9 ** x)
annealer = LearningRateScheduler(get_lr)
log_dir = os.path.join(log_path, run_name)
print('log_dir:' + log_dir)
tensorBoard = TensorBoard(log_dir=log_dir)
In [12]:
steps_per_epoch = int(len(train_generator.classes)/batch_size)
validation_steps = int(len(val_generator.classes)/batch_size)
test_steps = int(len(test_generator.classes)/batch_size)+1
print(steps_per_epoch)
print(validation_steps)
print(test_steps)
print(len(test_generator.classes), test_steps*batch_size)
In [13]:
%%time
hist = model.fit_generator(train_generator,
steps_per_epoch=steps_per_epoch,
epochs=50,
verbose=2,
callbacks=[annealer, tensorBoard],
validation_data=val_generator,
validation_steps=validation_steps,
class_weight=None,
max_queue_size=128,
workers=32,
use_multiprocessing=False,
shuffle=False,
initial_epoch=0)
In [14]:
%%time
final_loss, final_acc = model.evaluate_generator(val_generator, steps=validation_steps, max_queue_size=128, workers=32, use_multiprocessing=False)
print("Final loss: {0:.4f}, final accuracy: {1:.4f}".format(final_loss, final_acc))
In [15]:
run_name_acc = run_name + '_' + str(int(final_acc*10000)).zfill(4)
print(run_name_acc)
In [16]:
histories = pd.DataFrame(hist.history)
histories['epoch'] = hist.epoch
print(histories.columns)
histories_file = os.path.join(model_path, run_name_acc + '.csv')
histories.to_csv(histories_file, index=False)
In [17]:
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(hist.history['loss'], color='b')
plt.plot(hist.history['val_loss'], color='r')
plt.show()
plt.plot(hist.history['acc'], color='b')
plt.plot(hist.history['val_acc'], color='r')
plt.show()
In [18]:
saveModel(model, run_name_acc)
In [19]:
df2 = pd.read_csv('.\\input\\sample_submission.csv')
n_test = len(df2)
print(df2.shape)
In [20]:
%%time
y_pred = model.predict_generator(test_generator, steps=test_steps, max_queue_size=128, workers=16, use_multiprocessing=False, verbose=1)
print(y_pred.shape)
In [21]:
print(y_pred.shape)
y_pred = y_pred[0:n_test]
print(y_pred.shape)
# print(y_pred[-10:-5])
# print(test_generator.filenames[-10:-5])
# print(df2[-10:-5])
In [22]:
for i in range(0, 120):
df2.iloc[:,[i+1]] = y_pred[:,i]
if not os.path.exists(output_path):
os.mkdir(output_path)
pred_file = os.path.join(output_path, 'pred_' + run_name_acc + '.csv')
df2.to_csv(pred_file, index=None)
In [23]:
print(run_name_acc)
print('Done!')
In [ ]: